home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume9 / uemacs3.8b / part06 < prev    next >
Encoding:
Internet Message Format  |  1987-03-12  |  49.0 KB

  1. Subject:  v09i038:  MicroEMACS 3.8b, Part06/14
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence)
  6. Mod.sources: Volume 9, Issue 38
  7. Archive-name: uemacs3.8b/Part06
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If this archive is complete, you will see the message:
  13. #        "End of archive 6 (of 14)."
  14. # Contents:  bind.c buffer.c word.c
  15. # Wrapped by rs@mirror on Fri Mar 13 13:24:12 1987
  16. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  17. echo shar: Extracting \"bind.c\" \(14963 characters\)
  18. if test -f bind.c ; then 
  19.   echo shar: Will not over-write existing file \"bind.c\"
  20. else
  21. sed "s/^X//" >bind.c <<'END_OF_bind.c'
  22. X/*    This file is for functions having to do with key bindings,
  23. X    descriptions, help commands and startup file.
  24. X
  25. X    written 11-feb-86 by Daniel Lawrence
  26. X                                */
  27. X
  28. X#include    <stdio.h>
  29. X#include    "estruct.h"
  30. X#include    "edef.h"
  31. X#include    "epath.h"
  32. X
  33. X#if    MEGAMAX & ST520
  34. Xoverlay    "bind"
  35. X#endif
  36. X
  37. Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
  38. X
  39. Xdeskey(f, n)    /* describe the command for a certain key */
  40. X
  41. X{
  42. X    register int c;        /* command character to describe */
  43. X    register char *ptr;    /* string pointer to scan output strings */
  44. X    register KEYTAB *ktp;    /* pointer into the command table */
  45. X    register int found;    /* matched command flag */
  46. X    register NBIND *nptr;    /* pointer into the name binding table */
  47. X    char outseq[80];    /* output buffer for command sequence */
  48. X
  49. X    /* prompt the user to type us a key to describe */
  50. X    mlwrite(": describe-key ");
  51. X
  52. X    /* get the command sequence to describe */
  53. X    c = getckey(FALSE);            /* get a command sequence */
  54. X
  55. X    /* change it to something we can print as well */
  56. X    cmdstr(c, &outseq[0]);
  57. X
  58. X    /* and dump it out */
  59. X    ptr = &outseq[0];
  60. X    while (*ptr)
  61. X        TTputc(*ptr++);
  62. X    TTputc(' ');        /* space it out */
  63. X
  64. X    /* find the right ->function */
  65. X    ktp = &keytab[0];
  66. X    found = FALSE;
  67. X    while (ktp->k_fp != NULL) {
  68. X        if (ktp->k_code == c) {
  69. X            found = TRUE;
  70. X            break;
  71. X        }
  72. X        ++ktp;
  73. X    }
  74. X
  75. X    if (!found)
  76. X        strcpy(outseq,"Not Bound");
  77. X    else {
  78. X        /* match it against the name binding table */
  79. X        nptr = &names[0];
  80. X        strcpy(outseq,"[Bad binding]");
  81. X        while (nptr->n_func != NULL) {
  82. X            if (nptr->n_func == ktp->k_fp) {
  83. X                strcpy(outseq, nptr->n_name);
  84. X                break;
  85. X            }
  86. X            ++nptr;
  87. X        }
  88. X    }
  89. X
  90. X    /* output the command sequence */
  91. X    ptr = &outseq[0];
  92. X    while (*ptr)
  93. X        TTputc(*ptr++);
  94. X}
  95. X
  96. Xcmdstr(c, seq)    /* change a key command to a string we can print out */
  97. X
  98. Xint c;        /* sequence to translate */
  99. Xchar *seq;    /* destination string for sequence */
  100. X
  101. X{
  102. X    char *ptr;    /* pointer into current position in sequence */
  103. X
  104. X    ptr = seq;
  105. X
  106. X    /* apply meta sequence if needed */
  107. X    if (c & META) {
  108. X        *ptr++ = 'M';
  109. X        *ptr++ = '-';
  110. X    }
  111. X
  112. X    /* apply ^X sequence if needed */
  113. X    if (c & CTLX) {
  114. X        *ptr++ = '^';
  115. X        *ptr++ = 'X';
  116. X    }
  117. X
  118. X    /* apply SPEC sequence if needed */
  119. X    if (c & SPEC) {
  120. X        *ptr++ = 'F';
  121. X        *ptr++ = 'N';
  122. X    }
  123. X
  124. X    /* apply control sequence if needed */
  125. X    if (c & CTRL) {
  126. X        *ptr++ = '^';
  127. X    }
  128. X
  129. X    c = c & 255;    /* strip the prefixes */
  130. X
  131. X    /* and output the final sequence */
  132. X
  133. X    *ptr++ = c;
  134. X    *ptr = 0;    /* terminate the string */
  135. X}
  136. X
  137. Xhelp(f, n)    /* give me some help!!!!
  138. X           bring up a fake buffer and read the help file
  139. X           into it with view mode            */
  140. X{
  141. X    register WINDOW *wp;    /* scaning pointer to windows */
  142. X    register BUFFER *bp;    /* buffer pointer to help */
  143. X    char *fname;        /* ptr to file returned by flook() */
  144. X
  145. X    /* first check if we are already here */
  146. X    bp = bfind("emacs.hlp", FALSE, BFINVS);
  147. X
  148. X    if (bp == NULL) {
  149. X        fname = flook(pathname[1], FALSE);
  150. X        if (fname == NULL) {
  151. X            mlwrite("[Help file is not online]");
  152. X            return(FALSE);
  153. X        }
  154. X    }
  155. X
  156. X    /* split the current window to make room for the help stuff */
  157. X    if (splitwind(FALSE, 1) == FALSE)
  158. X            return(FALSE);
  159. X
  160. X    if (bp == NULL) {
  161. X        /* and read the stuff in */
  162. X        if (getfile(fname, FALSE) == FALSE)
  163. X            return(FALSE);
  164. X    } else
  165. X        swbuffer(bp);
  166. X
  167. X    /* make this window in VIEW mode, update all mode lines */
  168. X    curwp->w_bufp->b_mode |= MDVIEW;
  169. X    curwp->w_bufp->b_flag |= BFINVS;
  170. X    wp = wheadp;
  171. X    while (wp != NULL) {
  172. X        wp->w_flag |= WFMODE;
  173. X        wp = wp->w_wndp;
  174. X    }
  175. X    return(TRUE);
  176. X}
  177. X
  178. Xint (*fncmatch(fname))() /* match fname to a function in the names table
  179. X                and return any match or NULL if none        */
  180. X
  181. Xchar *fname;    /* name to attempt to match */
  182. X
  183. X{
  184. X    register NBIND *ffp;    /* pointer to entry in name binding table */
  185. X
  186. X    /* scan through the table, returning any match */
  187. X    ffp = &names[0];
  188. X    while (ffp->n_func != NULL) {
  189. X        if (strcmp(fname, ffp->n_name) == 0)
  190. X            return(ffp->n_func);
  191. X        ++ffp;
  192. X    }
  193. X    return(NULL);
  194. X}
  195. X
  196. X/* bindtokey:    add a new key to the key binding table        */
  197. X
  198. Xbindtokey(f, n)
  199. X
  200. Xint f, n;    /* command arguments [IGNORED] */
  201. X
  202. X{
  203. X    register int c;        /* command key to bind */
  204. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  205. X    register char *ptr;    /* ptr to dump out input key string */
  206. X    register KEYTAB *ktp;    /* pointer into the command table */
  207. X    register int found;    /* matched command flag */
  208. X    char outseq[80];    /* output buffer for keystroke sequence */
  209. X    int (*getname())();
  210. X
  211. X    /* prompt the user to type in a key to bind */
  212. X    mlwrite(": bind-to-key ");
  213. X
  214. X    /* get the function name to bind it to */
  215. X    kfunc = getname();
  216. X    if (kfunc == NULL) {
  217. X        mlwrite("[No such function]");
  218. X        return(FALSE);
  219. X    }
  220. X    TTputc(' ');        /* space it out */
  221. X    TTflush();
  222. X
  223. X    /* get the command sequence to bind */
  224. X    c = getckey((kfunc == meta) || (kfunc == cex) ||
  225. X                (kfunc == unarg) || (kfunc == ctrlg));
  226. X
  227. X    /* change it to something we can print as well */
  228. X    cmdstr(c, &outseq[0]);
  229. X
  230. X    /* and dump it out */
  231. X    ptr = &outseq[0];
  232. X    while (*ptr)
  233. X        TTputc(*ptr++);
  234. X
  235. X    /* if the function is a prefix key */
  236. X    if (kfunc == meta || kfunc == cex ||
  237. X        kfunc == unarg || kfunc == ctrlg) {
  238. X
  239. X        /* search for an existing binding for the prefix key */
  240. X        ktp = &keytab[0];
  241. X        found = FALSE;
  242. X        while (ktp->k_fp != NULL) {
  243. X            if (ktp->k_fp == kfunc)
  244. X                unbindchar(ktp->k_code);
  245. X            ++ktp;
  246. X        }
  247. X
  248. X        /* reset the appropriate global prefix variable */
  249. X        if (kfunc == meta)
  250. X            metac = c;
  251. X        if (kfunc == cex)
  252. X            ctlxc = c;
  253. X        if (kfunc == unarg)
  254. X            reptc = c;
  255. X        if (kfunc == ctrlg)
  256. X            abortc = c;
  257. X    }
  258. X
  259. X    /* search the table to see if it exists */
  260. X    ktp = &keytab[0];
  261. X    found = FALSE;
  262. X    while (ktp->k_fp != NULL) {
  263. X        if (ktp->k_code == c) {
  264. X            found = TRUE;
  265. X            break;
  266. X        }
  267. X        ++ktp;
  268. X    }
  269. X
  270. X    if (found) {    /* it exists, just change it then */
  271. X        ktp->k_fp = kfunc;
  272. X    } else {    /* otherwise we need to add it to the end */
  273. X        /* if we run out of binding room, bitch */
  274. X        if (ktp >= &keytab[NBINDS]) {
  275. X            mlwrite("Binding table FULL!");
  276. X            return(FALSE);
  277. X        }
  278. X
  279. X        ktp->k_code = c;    /* add keycode */
  280. X        ktp->k_fp = kfunc;    /* and the function pointer */
  281. X        ++ktp;            /* and make sure the next is null */
  282. X        ktp->k_code = 0;
  283. X        ktp->k_fp = NULL;
  284. X    }
  285. X    return(TRUE);
  286. X}
  287. X
  288. X/* unbindkey:    delete a key from the key binding table    */
  289. X
  290. Xunbindkey(f, n)
  291. X
  292. Xint f, n;    /* command arguments [IGNORED] */
  293. X
  294. X{
  295. X    register int c;        /* command key to unbind */
  296. X    register char *ptr;    /* ptr to dump out input key string */
  297. X    char outseq[80];    /* output buffer for keystroke sequence */
  298. X
  299. X    /* prompt the user to type in a key to unbind */
  300. X    mlwrite(": unbind-key ");
  301. X
  302. X    /* get the command sequence to unbind */
  303. X    c = getckey(FALSE);        /* get a command sequence */
  304. X
  305. X    /* change it to something we can print as well */
  306. X    cmdstr(c, &outseq[0]);
  307. X
  308. X    /* and dump it out */
  309. X    ptr = &outseq[0];
  310. X    while (*ptr)
  311. X        TTputc(*ptr++);
  312. X
  313. X    /* if it isn't bound, bitch */
  314. X    if (unbindchar(c) == FALSE) {
  315. X        mlwrite("[Key not bound]");
  316. X        return(FALSE);
  317. X    }
  318. X    return(TRUE);
  319. X}
  320. X
  321. Xunbindchar(c)
  322. X
  323. Xint c;        /* command key to unbind */
  324. X
  325. X{
  326. X    register KEYTAB *ktp;    /* pointer into the command table */
  327. X    register KEYTAB *sktp;    /* saved pointer into the command table */
  328. X    register int found;    /* matched command flag */
  329. X
  330. X    /* search the table to see if the key exists */
  331. X    ktp = &keytab[0];
  332. X    found = FALSE;
  333. X    while (ktp->k_fp != NULL) {
  334. X        if (ktp->k_code == c) {
  335. X            found = TRUE;
  336. X            break;
  337. X        }
  338. X        ++ktp;
  339. X    }
  340. X
  341. X    /* if it isn't bound, bitch */
  342. X    if (!found)
  343. X        return(FALSE);
  344. X
  345. X    /* save the pointer and scan to the end of the table */
  346. X    sktp = ktp;
  347. X    while (ktp->k_fp != NULL)
  348. X        ++ktp;
  349. X    --ktp;        /* backup to the last legit entry */
  350. X
  351. X    /* copy the last entry to the current one */
  352. X    sktp->k_code = ktp->k_code;
  353. X    sktp->k_fp   = ktp->k_fp;
  354. X
  355. X    /* null out the last one */
  356. X    ktp->k_code = 0;
  357. X    ktp->k_fp = NULL;
  358. X    return(TRUE);
  359. X}
  360. X
  361. Xdesbind(f, n)    /* describe bindings
  362. X           bring up a fake buffer and list the key bindings
  363. X           into it with view mode            */
  364. X
  365. X#if    APROP
  366. X{
  367. X    buildlist(TRUE, "");
  368. X}
  369. X
  370. Xapro(f, n)    /* Apropos (List functions that match a substring) */
  371. X
  372. X{
  373. X    char mstring[NSTRING];    /* string to match cmd names to */
  374. X    int status;        /* status return */
  375. X
  376. X    status = mlreply("Apropos string: ", mstring, NSTRING - 1);
  377. X    if (status != TRUE)
  378. X        return(status);
  379. X
  380. X    return(buildlist(FALSE, mstring));
  381. X}
  382. X
  383. Xbuildlist(type, mstring)  /* build a binding list (limited or full) */
  384. X
  385. Xint type;    /* true = full list,   false = partial list */
  386. Xchar *mstring;    /* match string if a partial list */
  387. X
  388. X#endif
  389. X{
  390. X    register WINDOW *wp;    /* scnaning pointer to windows */
  391. X    register KEYTAB *ktp;    /* pointer into the command table */
  392. X    register NBIND *nptr;    /* pointer into the name binding table */
  393. X    register BUFFER *bp;    /* buffer to put binding list into */
  394. X    char *strp;        /* pointer int string to send */
  395. X    int cpos;        /* current position to use in outseq */
  396. X    char outseq[80];    /* output buffer for keystroke sequence */
  397. X
  398. X    /* split the current window to make room for the binding list */
  399. X    if (splitwind(FALSE, 1) == FALSE)
  400. X            return(FALSE);
  401. X
  402. X    /* and get a buffer for it */
  403. X    bp = bfind("Binding list", TRUE, 0);
  404. X    if (bp == NULL || bclear(bp) == FALSE) {
  405. X        mlwrite("Can not display binding list");
  406. X        return(FALSE);
  407. X    }
  408. X
  409. X    /* let us know this is in progress */
  410. X    mlwrite("[Building binding list]");
  411. X
  412. X    /* disconect the current buffer */
  413. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  414. X                curbp->b_dotp  = curwp->w_dotp;
  415. X                curbp->b_doto  = curwp->w_doto;
  416. X                curbp->b_markp = curwp->w_markp;
  417. X                curbp->b_marko = curwp->w_marko;
  418. X        }
  419. X
  420. X    /* connect the current window to this buffer */
  421. X    curbp = bp;    /* make this buffer current in current window */
  422. X    bp->b_mode = 0;        /* no modes active in binding list */
  423. X    bp->b_nwnd++;        /* mark us as more in use */
  424. X    wp = curwp;
  425. X    wp->w_bufp = bp;
  426. X    wp->w_linep = bp->b_linep;
  427. X    wp->w_flag = WFHARD|WFFORCE;
  428. X    wp->w_dotp = bp->b_dotp;
  429. X    wp->w_doto = bp->b_doto;
  430. X    wp->w_markp = NULL;
  431. X    wp->w_marko = 0;
  432. X
  433. X    /* build the contents of this window, inserting it line by line */
  434. X    nptr = &names[0];
  435. X    while (nptr->n_func != NULL) {
  436. X
  437. X        /* add in the command name */
  438. X        strcpy(outseq, nptr->n_name);
  439. X        cpos = strlen(outseq);
  440. X        
  441. X#if    APROP
  442. X        /* if we are executing an apropos command..... */
  443. X        if (type == FALSE &&
  444. X            /* and current string doesn't include the search string */
  445. X            strinc(outseq, mstring) == FALSE)
  446. X            goto fail;
  447. X#endif
  448. X        /* search down any keys bound to this */
  449. X        ktp = &keytab[0];
  450. X        while (ktp->k_fp != NULL) {
  451. X            if (ktp->k_fp == nptr->n_func) {
  452. X                /* padd out some spaces */
  453. X                while (cpos < 25)
  454. X                    outseq[cpos++] = ' ';
  455. X
  456. X                /* add in the command sequence */
  457. X                cmdstr(ktp->k_code, &outseq[cpos]);
  458. X                while (outseq[cpos] != 0)
  459. X                    ++cpos;
  460. X
  461. X                /* and add it as a line into the buffer */
  462. X                strp = &outseq[0];
  463. X                while (*strp != 0)
  464. X                    linsert(1, *strp++);
  465. X                lnewline();
  466. X
  467. X                cpos = 0;    /* and clear the line */
  468. X            }
  469. X            ++ktp;
  470. X        }
  471. X
  472. X        /* if no key was bound, we need to dump it anyway */
  473. X        if (cpos > 0) {
  474. X            outseq[cpos] = 0;
  475. X            strp = &outseq[0];
  476. X            while (*strp != 0)
  477. X                linsert(1, *strp++);
  478. X            lnewline();
  479. X        }
  480. X
  481. Xfail:        /* and on to the next name */
  482. X        ++nptr;
  483. X    }
  484. X
  485. X    curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  486. X    curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  487. X    wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
  488. X    wp->w_doto = 0;
  489. X    wp = wheadp;            /* and update ALL mode lines */
  490. X    while (wp != NULL) {
  491. X        wp->w_flag |= WFMODE;
  492. X        wp = wp->w_wndp;
  493. X    }
  494. X    mlwrite("");    /* clear the mode line */
  495. X    return(TRUE);
  496. X}
  497. X
  498. X#if    APROP
  499. Xstrinc(source, sub)    /* does source include sub? */
  500. X
  501. Xchar *source;    /* string to search in */
  502. Xchar *sub;    /* substring to look for */
  503. X
  504. X{
  505. X    char *sp;    /* ptr into source */
  506. X    char *nxtsp;    /* next ptr into source */
  507. X    char *tp;    /* ptr into substring */
  508. X
  509. X    /* for each character in the source string */
  510. X    sp = source;
  511. X    while (*sp) {
  512. X        tp = sub;
  513. X        nxtsp = sp;
  514. X
  515. X        /* is the substring here? */
  516. X        while (*tp) {
  517. X            if (*nxtsp++ != *tp)
  518. X                break;
  519. X            else
  520. X                tp++;
  521. X        }
  522. X
  523. X        /* yes, return a success */
  524. X        if (*tp == 0)
  525. X            return(TRUE);
  526. X
  527. X        /* no, onward */
  528. X        sp++;
  529. X    }
  530. X    return(FALSE);
  531. X}
  532. X#endif
  533. X
  534. Xgetckey(mflag)    /* get a command key sequence from the keyboard    */
  535. X
  536. Xint mflag;    /* going for a meta sequence? */
  537. X
  538. X{
  539. X    register int c;        /* character fetched */
  540. X    register char *tp;    /* pointer into the token */
  541. X    char tok[NSTRING];    /* command incoming */
  542. X
  543. X    /* check to see if we are executing a command line */
  544. X    if (clexec) {
  545. X        macarg(tok);    /* get the next token */
  546. X
  547. X        /* parse it up */
  548. X        tp = &tok[0];
  549. X        c = 0;
  550. X
  551. X        /* first, the META prefix */
  552. X        if (*tp == 'M' && *(tp+1) == '-') {
  553. X            c = META;
  554. X            tp += 2;
  555. X        }
  556. X
  557. X        /* next the function prefix */
  558. X        if (*tp == 'F' && *(tp+1) == 'N') {
  559. X            c |= SPEC;
  560. X            tp += 2;
  561. X        }
  562. X
  563. X        /* control-x as well... */
  564. X        if (*tp == '^' && *(tp+1) == 'X') {
  565. X            c |= CTLX;
  566. X            tp += 2;
  567. X        }
  568. X
  569. X        /* a control char? */
  570. X        if (*tp == '^' && *(tp+1) != 0) {
  571. X            c |= CTRL;
  572. X            ++tp;
  573. X        }
  574. X
  575. X        /* make sure we are not lower case */
  576. X        if (c >= 'a' && c <= 'z')
  577. X            c -= 32;
  578. X
  579. X        /* the final sequence... */
  580. X        c |= *tp;
  581. X
  582. X        return(c);
  583. X    }
  584. X
  585. X    /* or the normal way */
  586. X    if (mflag)
  587. X        c = get1key();
  588. X    else
  589. X        c = getcmd();
  590. X    return(c);
  591. X}
  592. X
  593. X/* execute the startup file */
  594. X
  595. Xstartup(sfname)
  596. X
  597. Xchar *sfname;    /* name of startup file (null if default) */
  598. X
  599. X{
  600. X    char *fname;    /* resulting file name to execute */
  601. X
  602. X    /* look up the startup file */
  603. X    if (*sfname != 0)
  604. X        fname = flook(sfname, TRUE);
  605. X    else
  606. X        fname = flook(pathname[0], TRUE);
  607. X
  608. X    /* if it isn't around, don't sweat it */
  609. X    if (fname == NULL)
  610. X        return(TRUE);
  611. X
  612. X    /* otherwise, execute the sucker */
  613. X    return(dofile(fname));
  614. X}
  615. X
  616. X/*    Look up the existance of a file along the normal or PATH
  617. X    environment variable. Look first in the HOME directory if
  618. X    asked and possible
  619. X*/
  620. X
  621. Xchar *flook(fname, hflag)
  622. X
  623. Xchar *fname;    /* base file name to search for */
  624. Xint hflag;    /* Look in the HOME environment variable first? */
  625. X
  626. X{
  627. X    register char *home;    /* path to home directory */
  628. X    register char *path;    /* environmental PATH variable */
  629. X    register char *sp;    /* pointer into path spec */
  630. X    register int i;        /* index */
  631. X    register int status;    /* return status */
  632. X    static char fspec[NSTRING];    /* full path spec to search */
  633. X    char *getenv();
  634. X
  635. X#if    ((MSDOS | AMIGA) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
  636. X
  637. X    if (hflag) {
  638. X        home = getenv("HOME");
  639. X        if (home != NULL) {
  640. X            /* build home dir file spec */
  641. X            strcpy(fspec, home);
  642. X            strcat(fspec, "/");
  643. X            strcat(fspec, fname);
  644. X
  645. X            /* and try it out */
  646. X            status = ffropen(fspec);
  647. X            if (status == FIOSUC) {
  648. X                ffclose();
  649. X                return(fspec);
  650. X            }
  651. X        }
  652. X    }
  653. X
  654. X    /* get the PATH variable */
  655. X    path = getenv("PATH");
  656. X    if (path != NULL)
  657. X        while (*path) {
  658. X
  659. X            /* build next possible file spec */
  660. X            sp = fspec;
  661. X            while (*path && (*path != PATHCHR))
  662. X                *sp++ = *path++;
  663. X            *sp++ = '/';
  664. X            *sp = 0;
  665. X            strcat(fspec, fname);
  666. X
  667. X            /* and try it out */
  668. X            status = ffropen(fspec);
  669. X            if (status == FIOSUC) {
  670. X                ffclose();
  671. X                return(fspec);
  672. X            }
  673. X
  674. X            if (*path == PATHCHR)
  675. X                ++path;
  676. X        }
  677. X#endif
  678. X
  679. X    /* look it up via the old table method */
  680. X    for (i=2; i < NPNAMES; i++) {
  681. X        strcpy(fspec, pathname[i]);
  682. X        strcat(fspec, fname);
  683. X
  684. X        /* and try it out */
  685. X        status = ffropen(fspec);
  686. X        if (status == FIOSUC) {
  687. X            ffclose();
  688. X            return(fspec);
  689. X        }
  690. X    }
  691. X
  692. X    return(NULL);    /* no such luck */
  693. X}
  694. X
  695. END_OF_bind.c
  696. if test 14963 -ne `wc -c <bind.c`; then
  697.     echo shar: \"bind.c\" unpacked with wrong size!
  698. fi
  699. # end of overwriting check
  700. fi
  701. echo shar: Extracting \"buffer.c\" \(15529 characters\)
  702. if test -f buffer.c ; then 
  703.   echo shar: Will not over-write existing file \"buffer.c\"
  704. else
  705. sed "s/^X//" >buffer.c <<'END_OF_buffer.c'
  706. X/*
  707. X * Buffer management.
  708. X * Some of the functions are internal,
  709. X * and some are actually attached to user
  710. X * keys. Like everyone else, they set hints
  711. X * for the display system.
  712. X */
  713. X#include        <stdio.h>
  714. X#include    "estruct.h"
  715. X#include        "edef.h"
  716. X
  717. X#if    MEGAMAX & ST520
  718. Xoverlay    "buffer"
  719. X#endif
  720. X
  721. X/*
  722. X * Attach a buffer to a window. The
  723. X * values of dot and mark come from the buffer
  724. X * if the use count is 0. Otherwise, they come
  725. X * from some other window.
  726. X */
  727. Xusebuffer(f, n)
  728. X{
  729. X        register BUFFER *bp;
  730. X        register int    s;
  731. X        char            bufn[NBUFN];
  732. X
  733. X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  734. X                return (s);
  735. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  736. X                return (FALSE);
  737. X    return(swbuffer(bp));
  738. X}
  739. X
  740. Xnextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  741. X
  742. X{
  743. X        register BUFFER *bp;
  744. X
  745. X    bp = curbp->b_bufp;
  746. X    /* cycle through the buffers to find an eligable one */
  747. X    while (bp == NULL || bp->b_flag & BFINVS) {
  748. X        if (bp == NULL)
  749. X            bp = bheadp;
  750. X        else
  751. X            bp = bp->b_bufp;
  752. X    }
  753. X    return(swbuffer(bp));
  754. X}
  755. X
  756. Xswbuffer(bp)    /* make buffer BP current */
  757. X
  758. XBUFFER *bp;
  759. X
  760. X{
  761. X        register WINDOW *wp;
  762. X
  763. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  764. X                curbp->b_dotp  = curwp->w_dotp;
  765. X                curbp->b_doto  = curwp->w_doto;
  766. X                curbp->b_markp = curwp->w_markp;
  767. X                curbp->b_marko = curwp->w_marko;
  768. X        }
  769. X        curbp = bp;                             /* Switch.              */
  770. X    if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  771. X        /* read it in and activate it */
  772. X        readin(curbp->b_fname, TRUE);
  773. X        curbp->b_dotp = lforw(curbp->b_linep);
  774. X        curbp->b_doto = 0;
  775. X        curbp->b_active = TRUE;
  776. X    }
  777. X        curwp->w_bufp  = bp;
  778. X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  779. X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  780. X        if (bp->b_nwnd++ == 0) {                /* First use.           */
  781. X                curwp->w_dotp  = bp->b_dotp;
  782. X                curwp->w_doto  = bp->b_doto;
  783. X                curwp->w_markp = bp->b_markp;
  784. X                curwp->w_marko = bp->b_marko;
  785. X                return (TRUE);
  786. X        }
  787. X        wp = wheadp;                            /* Look for old.        */
  788. X        while (wp != NULL) {
  789. X                if (wp!=curwp && wp->w_bufp==bp) {
  790. X                        curwp->w_dotp  = wp->w_dotp;
  791. X                        curwp->w_doto  = wp->w_doto;
  792. X                        curwp->w_markp = wp->w_markp;
  793. X                        curwp->w_marko = wp->w_marko;
  794. X                        break;
  795. X                }
  796. X                wp = wp->w_wndp;
  797. X        }
  798. X        return (TRUE);
  799. X}
  800. X
  801. X/*
  802. X * Dispose of a buffer, by name.
  803. X * Ask for the name. Look it up (don't get too
  804. X * upset if it isn't there at all!). Get quite upset
  805. X * if the buffer is being displayed. Clear the buffer (ask
  806. X * if the buffer has been changed). Then free the header
  807. X * line and the buffer header. Bound to "C-X K".
  808. X */
  809. Xkillbuffer(f, n)
  810. X
  811. X{
  812. X    register BUFFER *bp;
  813. X        register int    s;
  814. X        char bufn[NBUFN];
  815. X
  816. X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  817. X                return(s);
  818. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  819. X                return (TRUE);
  820. X    if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  821. X            return (TRUE);        /* by doing nothing.    */
  822. X    return(zotbuf(bp));
  823. X}
  824. X
  825. Xzotbuf(bp)    /* kill the buffer pointed to by bp */
  826. X
  827. Xregister BUFFER *bp;
  828. X
  829. X{
  830. X        register BUFFER *bp1;
  831. X        register BUFFER *bp2;
  832. X        register int    s;
  833. X
  834. X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  835. X                mlwrite("Buffer is being displayed");
  836. X                return (FALSE);
  837. X        }
  838. X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  839. X                return (s);
  840. X        free((char *) bp->b_linep);             /* Release header line. */
  841. X        bp1 = NULL;                             /* Find the header.     */
  842. X        bp2 = bheadp;
  843. X        while (bp2 != bp) {
  844. X                bp1 = bp2;
  845. X                bp2 = bp2->b_bufp;
  846. X        }
  847. X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  848. X        if (bp1 == NULL)                        /* Unlink it.           */
  849. X                bheadp = bp2;
  850. X        else
  851. X                bp1->b_bufp = bp2;
  852. X        free((char *) bp);                      /* Release buffer block */
  853. X        return (TRUE);
  854. X}
  855. X
  856. Xnamebuffer(f,n)        /*    Rename the current buffer    */
  857. X
  858. Xint f, n;        /* default Flag & Numeric arg */
  859. X
  860. X{
  861. X    register BUFFER *bp;    /* pointer to scan through all buffers */
  862. X    char bufn[NBUFN];    /* buffer to hold buffer name */
  863. X
  864. X    /* prompt for and get the new buffer name */
  865. Xask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  866. X        return(FALSE);
  867. X
  868. X    /* and check for duplicates */
  869. X    bp = bheadp;
  870. X    while (bp != NULL) {
  871. X        if (bp != curbp) {
  872. X            /* if the names the same */
  873. X            if (strcmp(bufn, bp->b_bname) == 0)
  874. X                goto ask;  /* try again */
  875. X        }
  876. X        bp = bp->b_bufp;    /* onward */
  877. X    }
  878. X
  879. X    strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  880. X    curwp->w_flag |= WFMODE;    /* make mode line replot */
  881. X    mlerase();
  882. X    return(TRUE);
  883. X}
  884. X
  885. X/*
  886. X * List all of the active
  887. X * buffers. First update the special
  888. X * buffer that holds the list. Next make
  889. X * sure at least 1 window is displaying the
  890. X * buffer list, splitting the screen if this
  891. X * is what it takes. Lastly, repaint all of
  892. X * the windows that are displaying the
  893. X * list. Bound to "C-X C-B".
  894. X */
  895. Xlistbuffers(f, n)
  896. X{
  897. X        register WINDOW *wp;
  898. X        register BUFFER *bp;
  899. X        register int    s;
  900. X
  901. X        if ((s=makelist()) != TRUE)
  902. X                return (s);
  903. X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  904. X                if ((wp=wpopup()) == NULL)
  905. X                        return (FALSE);
  906. X                bp = wp->w_bufp;
  907. X                if (--bp->b_nwnd == 0) {
  908. X                        bp->b_dotp  = wp->w_dotp;
  909. X                        bp->b_doto  = wp->w_doto;
  910. X                        bp->b_markp = wp->w_markp;
  911. X                        bp->b_marko = wp->w_marko;
  912. X                }
  913. X                wp->w_bufp  = blistp;
  914. X                ++blistp->b_nwnd;
  915. X        }
  916. X        wp = wheadp;
  917. X        while (wp != NULL) {
  918. X                if (wp->w_bufp == blistp) {
  919. X                        wp->w_linep = lforw(blistp->b_linep);
  920. X                        wp->w_dotp  = lforw(blistp->b_linep);
  921. X                        wp->w_doto  = 0;
  922. X                        wp->w_markp = NULL;
  923. X                        wp->w_marko = 0;
  924. X                        wp->w_flag |= WFMODE|WFHARD;
  925. X                }
  926. X                wp = wp->w_wndp;
  927. X        }
  928. X        return (TRUE);
  929. X}
  930. X
  931. X/*
  932. X * This routine rebuilds the
  933. X * text in the special secret buffer
  934. X * that holds the buffer list. It is called
  935. X * by the list buffers command. Return TRUE
  936. X * if everything works. Return FALSE if there
  937. X * is an error (if there is no memory).
  938. X */
  939. Xmakelist()
  940. X{
  941. X        register char   *cp1;
  942. X        register char   *cp2;
  943. X        register int    c;
  944. X        register BUFFER *bp;
  945. X        register LINE   *lp;
  946. X        register int    s;
  947. X    register int    i;
  948. X        long    nbytes;        /* # of bytes in current buffer */
  949. X        char            b[7+1];
  950. X        char            line[128];
  951. X
  952. X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  953. X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  954. X                return (s);
  955. X        strcpy(blistp->b_fname, "");
  956. X        if (addline("AC MODES       Size Buffer        File") == FALSE
  957. X        ||  addline("-- -----       ---- ------        ----") == FALSE)
  958. X                return (FALSE);
  959. X        bp = bheadp;                            /* For all buffers      */
  960. X
  961. X    /* build line to report global mode settings */
  962. X    cp1 = &line[0];
  963. X    *cp1++ = ' ';
  964. X    *cp1++ = ' ';
  965. X    *cp1++ = ' ';
  966. X
  967. X    /* output the mode codes */
  968. X    for (i = 0; i < NUMMODES; i++)
  969. X        if (gmode & (1 << i))
  970. X            *cp1++ = modecode[i];
  971. X        else
  972. X            *cp1++ = '.';
  973. X    strcpy(cp1, "         Global Modes");
  974. X    if (addline(line) == FALSE)
  975. X        return(FALSE);
  976. X
  977. X    /* output the list of buffers */
  978. X        while (bp != NULL) {
  979. X                if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
  980. X                        bp = bp->b_bufp;
  981. X                        continue;
  982. X                }
  983. X                cp1 = &line[0];                 /* Start at left edge   */
  984. X
  985. X        /* output status of ACTIVE flag (has the file been read in? */
  986. X                if (bp->b_active == TRUE)    /* "@" if activated       */
  987. X                        *cp1++ = '@';
  988. X                else
  989. X                        *cp1++ = ' ';
  990. X
  991. X        /* output status of changed flag */
  992. X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  993. X                        *cp1++ = '*';
  994. X                else
  995. X                        *cp1++ = ' ';
  996. X                *cp1++ = ' ';                   /* Gap.                 */
  997. X
  998. X        /* output the mode codes */
  999. X        for (i = 0; i < NUMMODES; i++) {
  1000. X            if (bp->b_mode & (1 << i))
  1001. X                *cp1++ = modecode[i];
  1002. X            else
  1003. X                *cp1++ = '.';
  1004. X        }
  1005. X                *cp1++ = ' ';                   /* Gap.                 */
  1006. X                nbytes = 0L;                    /* Count bytes in buf.  */
  1007. X                lp = lforw(bp->b_linep);
  1008. X                while (lp != bp->b_linep) {
  1009. X                        nbytes += (long)llength(lp)+1L;
  1010. X                        lp = lforw(lp);
  1011. X                }
  1012. X                ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  1013. X                cp2 = &b[0];
  1014. X                while ((c = *cp2++) != 0)
  1015. X                        *cp1++ = c;
  1016. X                *cp1++ = ' ';                   /* Gap.                 */
  1017. X                cp2 = &bp->b_bname[0];          /* Buffer name          */
  1018. X                while ((c = *cp2++) != 0)
  1019. X                        *cp1++ = c;
  1020. X                cp2 = &bp->b_fname[0];          /* File name            */
  1021. X                if (*cp2 != 0) {
  1022. X                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  1023. X                                *cp1++ = ' ';
  1024. X                        while ((c = *cp2++) != 0) {
  1025. X                                if (cp1 < &line[128-1])
  1026. X                                        *cp1++ = c;
  1027. X                        }
  1028. X                }
  1029. X                *cp1 = 0;                       /* Add to the buffer.   */
  1030. X                if (addline(line) == FALSE)
  1031. X                        return (FALSE);
  1032. X                bp = bp->b_bufp;
  1033. X        }
  1034. X        return (TRUE);                          /* All done             */
  1035. X}
  1036. X
  1037. Xltoa(buf, width, num)
  1038. X
  1039. Xchar   buf[];
  1040. Xint    width;
  1041. Xlong   num;
  1042. X
  1043. X{
  1044. X        buf[width] = 0;                         /* End of string.       */
  1045. X        while (num >= 10) {                     /* Conditional digits.  */
  1046. X                buf[--width] = (int)(num%10L) + '0';
  1047. X                num /= 10L;
  1048. X        }
  1049. X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  1050. X        while (width != 0)                      /* Pad with blanks.     */
  1051. X                buf[--width] = ' ';
  1052. X}
  1053. X
  1054. X/*
  1055. X * The argument "text" points to
  1056. X * a string. Append this line to the
  1057. X * buffer list buffer. Handcraft the EOL
  1058. X * on the end. Return TRUE if it worked and
  1059. X * FALSE if you ran out of room.
  1060. X */
  1061. Xaddline(text)
  1062. Xchar    *text;
  1063. X{
  1064. X        register LINE   *lp;
  1065. X        register int    i;
  1066. X        register int    ntext;
  1067. X
  1068. X        ntext = strlen(text);
  1069. X        if ((lp=lalloc(ntext)) == NULL)
  1070. X                return (FALSE);
  1071. X        for (i=0; i<ntext; ++i)
  1072. X                lputc(lp, i, text[i]);
  1073. X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  1074. X        lp->l_bp = blistp->b_linep->l_bp;
  1075. X        blistp->b_linep->l_bp = lp;
  1076. X        lp->l_fp = blistp->b_linep;
  1077. X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  1078. X                blistp->b_dotp = lp;            /* move it to new line  */
  1079. X        return (TRUE);
  1080. X}
  1081. X
  1082. X/*
  1083. X * Look through the list of
  1084. X * buffers. Return TRUE if there
  1085. X * are any changed buffers. Buffers
  1086. X * that hold magic internal stuff are
  1087. X * not considered; who cares if the
  1088. X * list of buffer names is hacked.
  1089. X * Return FALSE if no buffers
  1090. X * have been changed.
  1091. X */
  1092. Xanycb()
  1093. X{
  1094. X        register BUFFER *bp;
  1095. X
  1096. X        bp = bheadp;
  1097. X        while (bp != NULL) {
  1098. X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  1099. X                        return (TRUE);
  1100. X                bp = bp->b_bufp;
  1101. X        }
  1102. X        return (FALSE);
  1103. X}
  1104. X
  1105. X/*
  1106. X * Find a buffer, by name. Return a pointer
  1107. X * to the BUFFER structure associated with it.
  1108. X * If the buffer is not found
  1109. X * and the "cflag" is TRUE, create it. The "bflag" is
  1110. X * the settings for the flags in in buffer.
  1111. X */
  1112. XBUFFER  *
  1113. Xbfind(bname, cflag, bflag)
  1114. Xregister char   *bname;
  1115. X{
  1116. X        register BUFFER *bp;
  1117. X    register BUFFER *sb;    /* buffer to insert after */
  1118. X        register LINE   *lp;
  1119. X    char *malloc();
  1120. X
  1121. X        bp = bheadp;
  1122. X        while (bp != NULL) {
  1123. X                if (strcmp(bname, bp->b_bname) == 0)
  1124. X                        return (bp);
  1125. X                bp = bp->b_bufp;
  1126. X        }
  1127. X        if (cflag != FALSE) {
  1128. X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  1129. X                        return (NULL);
  1130. X                if ((lp=lalloc(0)) == NULL) {
  1131. X                        free((char *) bp);
  1132. X                        return (NULL);
  1133. X                }
  1134. X        /* find the place in the list to insert this buffer */
  1135. X        if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  1136. X            /* insert at the beginning */
  1137. X                    bp->b_bufp = bheadp;
  1138. X                    bheadp = bp;
  1139. X            } else {
  1140. X            sb = bheadp;
  1141. X            while (sb->b_bufp != NULL) {
  1142. X                if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  1143. X                    break;
  1144. X                sb = sb->b_bufp;
  1145. X            }
  1146. X
  1147. X            /* and insert it */
  1148. X                   bp->b_bufp = sb->b_bufp;
  1149. X                sb->b_bufp = bp;
  1150. X               }
  1151. X
  1152. X        /* and set up the other buffer fields */
  1153. X        bp->b_active = TRUE;
  1154. X                bp->b_dotp  = lp;
  1155. X                bp->b_doto  = 0;
  1156. X                bp->b_markp = NULL;
  1157. X                bp->b_marko = 0;
  1158. X                bp->b_flag  = bflag;
  1159. X        bp->b_mode  = gmode;
  1160. X                bp->b_nwnd  = 0;
  1161. X                bp->b_linep = lp;
  1162. X                strcpy(bp->b_fname, "");
  1163. X                strcpy(bp->b_bname, bname);
  1164. X#if    CRYPT
  1165. X        bp->b_key[0] = 0;
  1166. X#endif
  1167. X                lp->l_fp = lp;
  1168. X                lp->l_bp = lp;
  1169. X        }
  1170. X        return (bp);
  1171. X}
  1172. X
  1173. X/*
  1174. X * This routine blows away all of the text
  1175. X * in a buffer. If the buffer is marked as changed
  1176. X * then we ask if it is ok to blow it away; this is
  1177. X * to save the user the grief of losing text. The
  1178. X * window chain is nearly always wrong if this gets
  1179. X * called; the caller must arrange for the updates
  1180. X * that are required. Return TRUE if everything
  1181. X * looks good.
  1182. X */
  1183. Xbclear(bp)
  1184. Xregister BUFFER *bp;
  1185. X{
  1186. X        register LINE   *lp;
  1187. X        register int    s;
  1188. X
  1189. X        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  1190. X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  1191. X        && (s=mlyesno("Discard changes")) != TRUE)
  1192. X                return (s);
  1193. X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  1194. X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  1195. X                lfree(lp);
  1196. X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  1197. X        bp->b_doto  = 0;
  1198. X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
  1199. X        bp->b_marko = 0;
  1200. X        return (TRUE);
  1201. X}
  1202. X
  1203. Xunmark(f, n)    /* unmark the current buffers change flag */
  1204. X
  1205. Xint f, n;    /* unused command arguments */
  1206. X
  1207. X{
  1208. X    curbp->b_flag &= ~BFCHG;
  1209. X    curwp->w_flag |= WFMODE;
  1210. X    return(TRUE);
  1211. X}
  1212. END_OF_buffer.c
  1213. if test 15529 -ne `wc -c <buffer.c`; then
  1214.     echo shar: \"buffer.c\" unpacked with wrong size!
  1215. fi
  1216. # end of overwriting check
  1217. fi
  1218. echo shar: Extracting \"word.c\" \(15895 characters\)
  1219. if test -f word.c ; then 
  1220.   echo shar: Will not over-write existing file \"word.c\"
  1221. else
  1222. sed "s/^X//" >word.c <<'END_OF_word.c'
  1223. X/*
  1224. X * The routines in this file implement commands that work word or a
  1225. X * paragraph at a time.  There are all sorts of word mode commands.  If I
  1226. X * do any sentence mode commands, they are likely to be put in this file. 
  1227. X */
  1228. X
  1229. X#if    MEGAMAX & ST520
  1230. Xoverlay    "word"
  1231. X#endif
  1232. X
  1233. X#include        <stdio.h>
  1234. X#include        "estruct.h"
  1235. X#include    "edef.h"
  1236. X
  1237. X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
  1238. X * line and stop on the first word-break or the beginning of the line. If we
  1239. X * reach the beginning of the line, jump back to the end of the word and start
  1240. X * a new line.  Otherwise, break the line at the word-break, eat it, and jump
  1241. X * back to the end of the word.
  1242. X * Returns TRUE on success, FALSE on errors.
  1243. X */
  1244. Xwrapword(f, n)
  1245. X
  1246. Xint f;        /* default flag */
  1247. Xint n;        /* numeric argument */
  1248. X
  1249. X{
  1250. X        register int cnt;    /* size of word wrapped to next line */
  1251. X    register int c;        /* charector temporary */
  1252. X
  1253. X    /* backup from the <NL> 1 char */
  1254. X        if (!backchar(0, 1))
  1255. X            return(FALSE);
  1256. X
  1257. X    /* back up until we aren't in a word,
  1258. X       make sure there is a break in the line */
  1259. X        cnt = 0;
  1260. X    while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
  1261. X                && (c != '\t')) {
  1262. X                cnt++;
  1263. X                if (!backchar(0, 1))
  1264. X                        return(FALSE);
  1265. X        /* if we make it to the beginning, start a new line */
  1266. X        if (curwp->w_doto == 0) {
  1267. X            gotoeol(FALSE, 0);
  1268. X            return(lnewline());
  1269. X        }
  1270. X        }
  1271. X
  1272. X    /* delete the forward white space */
  1273. X        if (!forwdel(0, 1))
  1274. X                return(FALSE);
  1275. X
  1276. X    /* put in a end of line */
  1277. X        if (!lnewline())
  1278. X                return(FALSE);
  1279. X
  1280. X    /* and past the first word */
  1281. X    while (cnt-- > 0) {
  1282. X        if (forwchar(FALSE, 1) == FALSE)
  1283. X            return(FALSE);
  1284. X    }
  1285. X        return(TRUE);
  1286. X}
  1287. X
  1288. X/*
  1289. X * Move the cursor backward by "n" words. All of the details of motion are
  1290. X * performed by the "backchar" and "forwchar" routines. Error if you try to
  1291. X * move beyond the buffers.
  1292. X */
  1293. Xbackword(f, n)
  1294. X{
  1295. X        if (n < 0)
  1296. X                return (forwword(f, -n));
  1297. X        if (backchar(FALSE, 1) == FALSE)
  1298. X                return (FALSE);
  1299. X        while (n--) {
  1300. X                while (inword() == FALSE) {
  1301. X                        if (backchar(FALSE, 1) == FALSE)
  1302. X                                return (FALSE);
  1303. X                }
  1304. X                while (inword() != FALSE) {
  1305. X                        if (backchar(FALSE, 1) == FALSE)
  1306. X                                return (FALSE);
  1307. X                }
  1308. X        }
  1309. X        return (forwchar(FALSE, 1));
  1310. X}
  1311. X
  1312. X/*
  1313. X * Move the cursor forward by the specified number of words. All of the motion
  1314. X * is done by "forwchar". Error if you try and move beyond the buffer's end.
  1315. X */
  1316. Xforwword(f, n)
  1317. X{
  1318. X        if (n < 0)
  1319. X                return (backword(f, -n));
  1320. X        while (n--) {
  1321. X#if    NFWORD
  1322. X                while (inword() != FALSE) {
  1323. X                        if (forwchar(FALSE, 1) == FALSE)
  1324. X                                return (FALSE);
  1325. X                }
  1326. X#endif
  1327. X                while (inword() == FALSE) {
  1328. X                        if (forwchar(FALSE, 1) == FALSE)
  1329. X                                return (FALSE);
  1330. X                }
  1331. X#if    NFWORD == 0
  1332. X                while (inword() != FALSE) {
  1333. X                        if (forwchar(FALSE, 1) == FALSE)
  1334. X                                return (FALSE);
  1335. X                }
  1336. X#endif
  1337. X        }
  1338. X    return(TRUE);
  1339. X}
  1340. X
  1341. X/*
  1342. X * Move the cursor forward by the specified number of words. As you move,
  1343. X * convert any characters to upper case. Error if you try and move beyond the
  1344. X * end of the buffer. Bound to "M-U".
  1345. X */
  1346. Xupperword(f, n)
  1347. X{
  1348. X        register int    c;
  1349. X
  1350. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1351. X        return(rdonly());    /* we are in read only mode    */
  1352. X        if (n < 0)
  1353. X                return (FALSE);
  1354. X        while (n--) {
  1355. X                while (inword() == FALSE) {
  1356. X                        if (forwchar(FALSE, 1) == FALSE)
  1357. X                                return (FALSE);
  1358. X                }
  1359. X                while (inword() != FALSE) {
  1360. X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
  1361. X                        if (c>='a' && c<='z') {
  1362. X                                c -= 'a'-'A';
  1363. X                                lputc(curwp->w_dotp, curwp->w_doto, c);
  1364. X                                lchange(WFHARD);
  1365. X                        }
  1366. X                        if (forwchar(FALSE, 1) == FALSE)
  1367. X                                return (FALSE);
  1368. X                }
  1369. X        }
  1370. X        return (TRUE);
  1371. X}
  1372. X
  1373. X/*
  1374. X * Move the cursor forward by the specified number of words. As you move
  1375. X * convert characters to lower case. Error if you try and move over the end of
  1376. X * the buffer. Bound to "M-L".
  1377. X */
  1378. Xlowerword(f, n)
  1379. X{
  1380. X        register int    c;
  1381. X
  1382. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1383. X        return(rdonly());    /* we are in read only mode    */
  1384. X        if (n < 0)
  1385. X                return (FALSE);
  1386. X        while (n--) {
  1387. X                while (inword() == FALSE) {
  1388. X                        if (forwchar(FALSE, 1) == FALSE)
  1389. X                                return (FALSE);
  1390. X                }
  1391. X                while (inword() != FALSE) {
  1392. X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
  1393. X                        if (c>='A' && c<='Z') {
  1394. X                                c += 'a'-'A';
  1395. X                                lputc(curwp->w_dotp, curwp->w_doto, c);
  1396. X                                lchange(WFHARD);
  1397. X                        }
  1398. X                        if (forwchar(FALSE, 1) == FALSE)
  1399. X                                return (FALSE);
  1400. X                }
  1401. X        }
  1402. X        return (TRUE);
  1403. X}
  1404. X
  1405. X/*
  1406. X * Move the cursor forward by the specified number of words. As you move
  1407. X * convert the first character of the word to upper case, and subsequent
  1408. X * characters to lower case. Error if you try and move past the end of the
  1409. X * buffer. Bound to "M-C".
  1410. X */
  1411. Xcapword(f, n)
  1412. X{
  1413. X        register int    c;
  1414. X
  1415. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1416. X        return(rdonly());    /* we are in read only mode    */
  1417. X        if (n < 0)
  1418. X                return (FALSE);
  1419. X        while (n--) {
  1420. X                while (inword() == FALSE) {
  1421. X                        if (forwchar(FALSE, 1) == FALSE)
  1422. X                                return (FALSE);
  1423. X                }
  1424. X                if (inword() != FALSE) {
  1425. X                        c = lgetc(curwp->w_dotp, curwp->w_doto);
  1426. X                        if (c>='a' && c<='z') {
  1427. X                                c -= 'a'-'A';
  1428. X                                lputc(curwp->w_dotp, curwp->w_doto, c);
  1429. X                                lchange(WFHARD);
  1430. X                        }
  1431. X                        if (forwchar(FALSE, 1) == FALSE)
  1432. X                                return (FALSE);
  1433. X                        while (inword() != FALSE) {
  1434. X                                c = lgetc(curwp->w_dotp, curwp->w_doto);
  1435. X                                if (c>='A' && c<='Z') {
  1436. X                                        c += 'a'-'A';
  1437. X                                        lputc(curwp->w_dotp, curwp->w_doto, c);
  1438. X                                        lchange(WFHARD);
  1439. X                                }
  1440. X                                if (forwchar(FALSE, 1) == FALSE)
  1441. X                                        return (FALSE);
  1442. X                        }
  1443. X                }
  1444. X        }
  1445. X        return (TRUE);
  1446. X}
  1447. X
  1448. X/*
  1449. X * Kill forward by "n" words. Remember the location of dot. Move forward by
  1450. X * the right number of words. Put dot back where it was and issue the kill
  1451. X * command for the right number of characters. Bound to "M-D".
  1452. X */
  1453. Xdelfword(f, n)
  1454. X{
  1455. X        register LINE   *dotp;
  1456. X        register int    doto;
  1457. X        long size;
  1458. X
  1459. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1460. X        return(rdonly());    /* we are in read only mode    */
  1461. X        if (n < 0)
  1462. X                return (FALSE);
  1463. X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  1464. X                kdelete();              /* last wasn't a kill.  */
  1465. X        thisflag |= CFKILL;
  1466. X        dotp = curwp->w_dotp;
  1467. X        doto = curwp->w_doto;
  1468. X        size = 0;
  1469. X        while (n--) {
  1470. X#if    NFWORD
  1471. X        if (curwp->w_doto == llength(curwp->w_dotp)) {
  1472. X            if (forwchar(FALSE,1) == FALSE)
  1473. X                return(FALSE);
  1474. X            ++size;
  1475. X        }
  1476. X
  1477. X        while (inword() != FALSE) {
  1478. X            if (forwchar(FALSE,1) == FALSE)
  1479. X                return(FALSE);
  1480. X            ++size;
  1481. X        }
  1482. X
  1483. X                while ((inword() == FALSE) &&
  1484. X                (curwp->w_doto != llength(curwp->w_dotp))) {
  1485. X                        if (forwchar(FALSE, 1) == FALSE)
  1486. X                                return (FALSE);
  1487. X                        ++size;
  1488. X                }
  1489. X#else
  1490. X                while (inword() == FALSE) {
  1491. X                        if (forwchar(FALSE, 1) == FALSE)
  1492. X                                return (FALSE);
  1493. X                        ++size;
  1494. X                }
  1495. X
  1496. X                while (inword() != FALSE) {
  1497. X                        if (forwchar(FALSE, 1) == FALSE)
  1498. X                                return (FALSE);
  1499. X                        ++size;
  1500. X                }
  1501. X#endif
  1502. X        }
  1503. X        curwp->w_dotp = dotp;
  1504. X        curwp->w_doto = doto;
  1505. X        return (ldelete(size, TRUE));
  1506. X}
  1507. X
  1508. X/*
  1509. X * Kill backwards by "n" words. Move backwards by the desired number of words,
  1510. X * counting the characters. When dot is finally moved to its resting place,
  1511. X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  1512. X */
  1513. Xdelbword(f, n)
  1514. X{
  1515. X        long size;
  1516. X
  1517. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1518. X        return(rdonly());    /* we are in read only mode    */
  1519. X        if (n < 0)
  1520. X                return (FALSE);
  1521. X        if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  1522. X                kdelete();              /* last wasn't a kill.  */
  1523. X        thisflag |= CFKILL;
  1524. X        if (backchar(FALSE, 1) == FALSE)
  1525. X                return (FALSE);
  1526. X        size = 0;
  1527. X        while (n--) {
  1528. X                while (inword() == FALSE) {
  1529. X                        if (backchar(FALSE, 1) == FALSE)
  1530. X                                return (FALSE);
  1531. X                        ++size;
  1532. X                }
  1533. X                while (inword() != FALSE) {
  1534. X                        if (backchar(FALSE, 1) == FALSE)
  1535. X                                return (FALSE);
  1536. X                        ++size;
  1537. X                }
  1538. X        }
  1539. X        if (forwchar(FALSE, 1) == FALSE)
  1540. X                return (FALSE);
  1541. X        return (ldelete(size, TRUE));
  1542. X}
  1543. X
  1544. X/*
  1545. X * Return TRUE if the character at dot is a character that is considered to be
  1546. X * part of a word. The word character list is hard coded. Should be setable.
  1547. X */
  1548. Xinword()
  1549. X{
  1550. X        register int    c;
  1551. X
  1552. X        if (curwp->w_doto == llength(curwp->w_dotp))
  1553. X                return (FALSE);
  1554. X        c = lgetc(curwp->w_dotp, curwp->w_doto);
  1555. X        if (c>='a' && c<='z')
  1556. X                return (TRUE);
  1557. X        if (c>='A' && c<='Z')
  1558. X                return (TRUE);
  1559. X        if (c>='0' && c<='9')
  1560. X                return (TRUE);
  1561. X        if (c=='$' || c=='_')                   /* For identifiers      */
  1562. X                return (TRUE);
  1563. X        return (FALSE);
  1564. X}
  1565. X
  1566. X#if    WORDPRO
  1567. Xfillpara(f, n)    /* Fill the current paragraph according to the current
  1568. X           fill column                        */
  1569. X
  1570. Xint f, n;    /* deFault flag and Numeric argument */
  1571. X
  1572. X{
  1573. X    register int c;            /* current char durring scan    */
  1574. X    register int wordlen;        /* length of current word    */
  1575. X    register int clength;        /* position on line during fill    */
  1576. X    register int i;            /* index during word copy    */
  1577. X    register int newlength;        /* tentative new line length    */
  1578. X    register int eopflag;        /* Are we at the End-Of-Paragraph? */
  1579. X    register int firstflag;        /* first word? (needs no space)    */
  1580. X    register LINE *eopline;        /* pointer to line just past EOP */
  1581. X    register int dotflag;        /* was the last char a period?    */
  1582. X    char wbuf[NSTRING];        /* buffer for current word    */
  1583. X
  1584. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1585. X        return(rdonly());    /* we are in read only mode    */
  1586. X    if (fillcol == 0) {    /* no fill column set */
  1587. X        mlwrite("No fill column set");
  1588. X        return(FALSE);
  1589. X    }
  1590. X
  1591. X    /* record the pointer to the line just past the EOP */
  1592. X    gotoeop(FALSE, 1);
  1593. X    eopline = lforw(curwp->w_dotp);
  1594. X
  1595. X    /* and back top the beginning of the paragraph */
  1596. X    gotobop(FALSE, 1);
  1597. X
  1598. X    /* initialize various info */
  1599. X    clength = curwp->w_doto;
  1600. X    if (clength && curwp->w_dotp->l_text[0] == TAB)
  1601. X        clength = 8;
  1602. X    wordlen = 0;
  1603. X    dotflag = FALSE;
  1604. X
  1605. X    /* scan through lines, filling words */
  1606. X    firstflag = TRUE;
  1607. X    eopflag = FALSE;
  1608. X    while (!eopflag) {
  1609. X        /* get the next character in the paragraph */
  1610. X        if (curwp->w_doto == llength(curwp->w_dotp)) {
  1611. X            c = ' ';
  1612. X            if (lforw(curwp->w_dotp) == eopline)
  1613. X                eopflag = TRUE;
  1614. X        } else
  1615. X            c = lgetc(curwp->w_dotp, curwp->w_doto);
  1616. X
  1617. X        /* and then delete it */
  1618. X        ldelete(1L, FALSE);
  1619. X
  1620. X        /* if not a separator, just add it in */
  1621. X        if (c != ' ' && c != '\t') {
  1622. X            dotflag = (c == '.');        /* was it a dot */
  1623. X            if (wordlen < NSTRING - 1)
  1624. X                wbuf[wordlen++] = c;
  1625. X        } else if (wordlen) {
  1626. X            /* at a word break with a word waiting */
  1627. X            /* calculate tantitive new length with word added */
  1628. X            newlength = clength + 1 + wordlen;
  1629. X            if (newlength <= fillcol) {
  1630. X                /* add word to current line */
  1631. X                if (!firstflag) {
  1632. X                    linsert(1, ' '); /* the space */
  1633. X                    ++clength;
  1634. X                }
  1635. X                firstflag = FALSE;
  1636. X            } else {
  1637. X                /* start a new line */
  1638. X                lnewline();
  1639. X                clength = 0;
  1640. X            }
  1641. X
  1642. X            /* and add the word in in either case */
  1643. X            for (i=0; i<wordlen; i++) {
  1644. X                linsert(1, wbuf[i]);
  1645. X                ++clength;
  1646. X            }
  1647. X            if (dotflag) {
  1648. X                linsert(1, ' ');
  1649. X                ++clength;
  1650. X            }
  1651. X            wordlen = 0;
  1652. X        }
  1653. X    }
  1654. X    /* and add a last newline for the end of our new paragraph */
  1655. X    lnewline();
  1656. X    return(TRUE);
  1657. X}
  1658. X
  1659. Xkillpara(f, n)    /* delete n paragraphs starting with the current one */
  1660. X
  1661. Xint f;    /* default flag */
  1662. Xint n;    /* # of paras to delete */
  1663. X
  1664. X{
  1665. X    register int status;    /* returned status of functions */
  1666. X
  1667. X    while (n--) {        /* for each paragraph to delete */
  1668. X
  1669. X        /* mark out the end and beginning of the para to delete */
  1670. X        gotoeop(FALSE, 1);
  1671. X
  1672. X        /* set the mark here */
  1673. X            curwp->w_markp = curwp->w_dotp;
  1674. X            curwp->w_marko = curwp->w_doto;
  1675. X
  1676. X        /* go to the beginning of the paragraph */
  1677. X        gotobop(FALSE, 1);
  1678. X        curwp->w_doto = 0;    /* force us to the beginning of line */
  1679. X    
  1680. X        /* and delete it */
  1681. X        if ((status = killregion(FALSE, 1)) != TRUE)
  1682. X            return(status);
  1683. X
  1684. X        /* and clean up the 2 extra lines */
  1685. X        ldelete(2L, TRUE);
  1686. X    }
  1687. X    return(TRUE);
  1688. X}
  1689. X
  1690. X
  1691. X/*    wordcount:    count the # of words in the marked region,
  1692. X            along with average word sizes, # of chars, etc,
  1693. X            and report on them.            */
  1694. X
  1695. Xwordcount(f, n)
  1696. X
  1697. Xint f, n;    /* ignored numeric arguments */
  1698. X
  1699. X{
  1700. X    register LINE *lp;    /* current line to scan */
  1701. X    register int offset;    /* current char to scan */
  1702. X    long size;        /* size of region left to count */
  1703. X    register int ch;    /* current character to scan */
  1704. X    register int wordflag;    /* are we in a word now? */
  1705. X    register int lastword;    /* were we just in a word? */
  1706. X    long nwords;        /* total # of words */
  1707. X    long nchars;        /* total number of chars */
  1708. X    int nlines;        /* total number of lines in region */
  1709. X    int avgch;        /* average number of chars/word */
  1710. X    int status;        /* status return code */
  1711. X    REGION region;        /* region to look at */
  1712. X
  1713. X    /* make sure we have a region to count */
  1714. X        if ((status = getregion(®ion)) != TRUE)
  1715. X                return(status);
  1716. X    lp = region.r_linep;
  1717. X    offset = region.r_offset;
  1718. X    size = region.r_size;
  1719. X
  1720. X    /* count up things */
  1721. X    lastword = FALSE;
  1722. X    nchars = 0L;
  1723. X    nwords = 0L;
  1724. X    nlines = 0;
  1725. X    while (size--) {
  1726. X
  1727. X        /* get the current character */
  1728. X        if (offset == llength(lp)) {    /* end of line */
  1729. X            ch = '\n';
  1730. X            lp = lforw(lp);
  1731. X            offset = 0;
  1732. X            ++nlines;
  1733. X        } else {
  1734. X            ch = lgetc(lp, offset);
  1735. X            ++offset;
  1736. X        }
  1737. X
  1738. X        /* and tabulate it */
  1739. X        wordflag = ((ch >= 'a' && ch <= 'z') ||
  1740. X                (ch >= 'A' && ch <= 'Z') ||
  1741. X                (ch >= '0' && ch <= '9') ||
  1742. X                (ch == '$' || ch == '_'));
  1743. X        if (wordflag == TRUE && lastword == FALSE)
  1744. X            ++nwords;
  1745. X        lastword = wordflag;
  1746. X        ++nchars;
  1747. X    }
  1748. X
  1749. X    /* and report on the info */
  1750. X    if (nwords > 0L)
  1751. X        avgch = (int)((100L * nchars) / nwords);
  1752. X    else
  1753. X        avgch = 0;
  1754. X
  1755. X    mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
  1756. X        nwords, nchars, nlines + 1, avgch);
  1757. X    return(TRUE);
  1758. X}
  1759. X#endif
  1760. END_OF_word.c
  1761. if test 15895 -ne `wc -c <word.c`; then
  1762.     echo shar: \"word.c\" unpacked with wrong size!
  1763. fi
  1764. # end of overwriting check
  1765. fi
  1766. echo shar: End of archive 6 \(of 14\).
  1767. cp /dev/null ark6isdone
  1768. MISSING=""
  1769. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1770.     if test ! -f ark${I}isdone ; then
  1771.     MISSING="${MISSING} ${I}"
  1772.     fi
  1773. done
  1774. if test "${MISSING}" = "" ; then
  1775.     echo You have unpacked all 14 archives.
  1776.     echo "See the readme file"
  1777.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1778. else
  1779.     echo You still need to unpack the following archives:
  1780.     echo "        " ${MISSING}
  1781. fi
  1782. ##  End of shell archive.
  1783. exit 0
  1784.